#ifndef XGE_XTYPE_TRAIT_H_
#define XGE_XTYPE_TRAIT_H_
#include "xge_common_config.h"
#include "xstring.h"

namespace xge {
  class Rect;
  class Point;
	// A simple type trait implementation
	// We simply use this to get the type of a specific value at the compile time
  namespace {
    // some helper function
    template < typename T > struct remove_const {
      typedef T value_type;
    };
    template < typename T > struct remove_const< const T > {
      typedef T value_type;
    };
    template < typename T > struct remove_volatile {
      typedef T value_type;
    };
    template < typename T > struct remove_volatile< volatile T> {
      typedef T value_type;
    };
  }
  // detail implementation function
  namespace {
    // int
    template < typename T > struct is_int_detail {
      static const bool value = false;
    };
    template <> struct is_int_detail<int> {
      static const bool value = true;
    };
    // bool
    template < typename T > struct is_bool_detail {
      static const bool value = false;
    };
    template <> struct is_bool_detail<bool> {
      static const bool value = true;
    };
    // float
    template < typename T > struct is_float_detail {
      static const bool value = false;
    };
    template <> struct is_float_detail< float > {
      static const bool value = true;
    };
    // char 
    template < typename T > struct is_char_detail {
      static const bool value = false;
    };

    template <> struct is_char_detail <char_t> {
      static const bool value = true;
    };
#ifdef XGE_USE_WIDE_CHAR
    template <> struct is_char_detail<char> {
      static const bool value = true;
    };
#else
    template <> struct is_char_detail<wchar_t> {
      static const bool value = true;
    };
#endif
    // string
    template < typename T > struct is_string_detail {
      static const bool value = false;
    };
    template <> struct is_string_detail<String> {
      static const bool value = true;
    };
    // rect
    template< typename T > struct is_rect_detail {
      static const bool value = false;
    };
    template<> struct is_rect_detail<Rect> {
      static const bool value = true;
    };
    // point
    template< typename T > struct is_point_detail {
      static const bool value = false;
    };
    template<> struct is_point_detail<Point> {
      static const bool value = true;
    };
  }

#define IMPLEMENT_TYPE_TEST(Type) template< typename T > struct _is_##Type { \
  static const bool value = is_##Type##_detail< \
  typename remove_volatile \
  < \
  typename remove_const< T >::value_type \
  >::value_type \
  >::value; }

#define IMPLEMENT_TYPE_FUNC(Type) template< typename T > bool is_##Type(const T &t){ \
  return _is_##Type<T>::value; \
  }

#define IMPLEMENT_TYPE_TRAIT(Type) \
  IMPLEMENT_TYPE_TEST(Type); \
  IMPLEMENT_TYPE_FUNC(Type)

  IMPLEMENT_TYPE_TRAIT(int)
  IMPLEMENT_TYPE_TRAIT(float)
  IMPLEMENT_TYPE_TRAIT(string)
  IMPLEMENT_TYPE_TRAIT(point)
  IMPLEMENT_TYPE_TRAIT(rect)
  IMPLEMENT_TYPE_TRAIT(char)
  IMPLEMENT_TYPE_TRAIT(bool)

#undef IMPLEMENT_TYPE_TEST
#undef IMPLEMENT_TYPE_FUNC
#undef IMPLEMENT_TYPE_TRAIT


}//namespace xge

#endif// XGE_XTYPE_TRAIT_H_